home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 4 / PC World Interactive 4.iso / online / appbar.EXE / csrc / appbar.cpp < prev    next >
C/C++ Source or Header  |  1996-09-20  |  39KB  |  1,106 lines

  1. // *********************************************************
  2. // AppBar -- Advanced Menu bar for Windows 95/NT
  3. // All code Copyright (C) 1995, 1996 by Mike Perham
  4. // mperham@cs.cornell.edu
  5. // 
  6. // This code MAY NOT be used for any other program without
  7. // my permission and is forbidden in any shareware/commercial
  8. // program.  This code is provided for educational use only
  9. // and there are no guarantees or promises implied.  Blah blah
  10. // *********************************************************
  11. // Notes:
  12. //
  13. //  The AppBar interface in Win95 is a bit quirky.  If you
  14. //  register an AppBar, the system reserves desktop space for
  15. //  the window.  If the window is autohide though, the space
  16. //  is still reserved and you get a hole where no windows can
  17. //  go.  To work around this, you need to unregister the AppBar
  18. //  or set its RECT to {0,0,0,0} (which is what I do).
  19. //
  20. //  The menus are stored in a doubly-linked list pointed to by
  21. //  glob_menu.  The structure looks (to me) just like the UI i.e.
  22. //
  23. //  --->menu--->menu--->menu-->NULL
  24. //      |        |
  25. //     app      app     etc...
  26. //      |        |
  27. //     app      app
  28. //
  29. // Set tabstops to 4
  30. //
  31.  
  32. #include "appbar.h"
  33. #include "globals.h"
  34.  
  35. // AppBar global variables
  36.  
  37. HWND ab_hwnd,                   // appbar window handle
  38.      EditDlg;                   // edit dlg handle
  39. ab_vars sys_vars;               // System variables
  40. menu_struct *glob_menu;         // Menus/Applications linked list
  41. user_options user_vars;         // User options
  42. WNDCLASS ab_wc;                 // window class
  43. HINSTANCE ab_inst;              // instance
  44. HMENU ab_menu, popup;           // menu handles
  45. app_list *applist;              // internal applist
  46. BOOL iserror = FALSE,           // error exit?
  47.      IsShown = TRUE;            // AB not autohidden at the moment?
  48. APPBARDATA abd;                 // structure for registering autohide bars with system
  49. char origdir[PATH_SIZE];        // dir of AppBar
  50.  
  51. // Program entry point and main loop
  52.  
  53. int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int cmdshow)
  54. {
  55.     MSG msg;
  56.  
  57.     ab_inst = hInst;
  58.     if (!init_app())                        // Read in Registry settings and command line
  59.         return FALSE;
  60.     if (!setup_win())                       // Create and set up window
  61.         return FALSE; 
  62.  
  63.     while (GetMessage(&msg, 0, 0, 0)) {
  64.         TranslateMessage(&msg);
  65.         DispatchMessage(&msg);
  66.     }
  67.     return msg.wParam;
  68. }
  69.  
  70. // Main Message loop for AppBar
  71.  
  72. LRESULT CALLBACK AppBarWinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  73. {   
  74.     app_struct *find;
  75.     static UINT timer = 0;
  76.     ATOM adam;
  77.  
  78.     switch (msg) {
  79.         case WM_TIMECHANGE:
  80.             modify_time();
  81.             return DefWindowProc(hWnd, msg, wParam, lParam);
  82.         case WM_WINDOWPOSCHANGED:
  83.             if (sys_vars.newshell) {
  84.                 abd.cbSize = sizeof(APPBARDATA);
  85.                 abd.hWnd = ab_hwnd;
  86.                 SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd);
  87.             }
  88.             return DefWindowProc(hWnd, msg, wParam, lParam);
  89.         case WM_DISPLAYCHANGE:
  90.             sys_vars.width = GetSystemMetrics(SM_CXSCREEN);
  91.             sys_vars.height = GetSystemMetrics(SM_CYSCREEN);
  92.             MoveWindow(ab_hwnd, 0, (user_vars.bottom ? sys_vars.height - AB_HEIGHT : 0),
  93.                         AB_WIDTH, AB_HEIGHT, TRUE);
  94.             return DefWindowProc(hWnd, msg, wParam, lParam);
  95.         case WM_POWERBROADCAST:
  96.             if (sys_vars.power) {
  97.                 SYSTEM_POWER_STATUS sps;
  98.                 GetSystemPowerStatus(&sps);
  99.                 sys_vars.battery = (sps.ACLineStatus ? FALSE : TRUE);
  100.                 modify_time();
  101.             }
  102.             return DefWindowProc(hWnd, msg, wParam, lParam);
  103.         case WM_HOTKEY:
  104.             HideAppBar(FALSE);
  105.             SetForegroundWindow(ab_hwnd);
  106.             // this is the code for pressing the Alt key down
  107.             // so we can make the menu highlight
  108.             PostMessage(ab_hwnd, WM_SYSKEYDOWN, VK_MENU,
  109.                         (((0x00000001 | 38<<16) | 1<<24) | 1<<29));
  110.             PostMessage(ab_hwnd, WM_SYSKEYUP, VK_MENU, 
  111.                         (((0x00000001 | 38<<16) | 1<<30) | 1<<31));
  112.             return TRUE;
  113.         case WM_NCRBUTTONDOWN:
  114.             POINTS pts;
  115.             pts = MAKEPOINTS(lParam);
  116.             TrackPopupMenu(popup, 0, pts.x, pts.y, 0, ab_hwnd, NULL);
  117.             return DefWindowProc(hWnd, msg, wParam, lParam);
  118.         case WM_SHOWWINDOW:
  119.             if (!RegisterHotKey(ab_hwnd, GlobalAddAtom("AppBar HotKey"), MOD_ALT | MOD_CONTROL, 0x5A /*z*/))
  120.                 if (!RegisterHotKey(ab_hwnd, GlobalAddAtom("AppBar HotKey"), MOD_ALT | MOD_CONTROL, 0x41 /*a*/))
  121.                     ab_message(ERROR_HOTKEY);
  122.             IsShown = TRUE;
  123.             SyncTime();
  124.             return DefWindowProc(hWnd, msg, wParam, lParam);
  125.         case WM_TIMER:
  126.             if (wParam == TIME_UPDATE)
  127.                 modify_time();
  128.               else if (wParam == HIDE_TIMER) {
  129.                 if (user_vars.autohide)
  130.                     if (GetActiveWindow() != ab_hwnd) {
  131.                         POINT pt;
  132.                         GetCursorPos(&pt);
  133.                         if (WindowFromPoint(pt) != ab_hwnd) {
  134.                             KillTimer(ab_hwnd, HIDE_TIMER);
  135.                             timer = 0;
  136.                             HideAppBar(TRUE);
  137.                         }
  138.                     }
  139.               } else if (wParam == SYNC_TIMER) {
  140.                   KillTimer(ab_hwnd, HIDE_TIMER);
  141.                   KillTimer(ab_hwnd, SYNC_TIMER);
  142.                   SetTimer(ab_hwnd, TIME_UPDATE, 10000, NULL);
  143.                   modify_time();
  144.             }
  145.             return 0;
  146.         case WM_ACTIVATE:
  147.             if ((LOWORD(wParam) == WA_INACTIVE) && user_vars.autohide) {
  148.                 HideAppBar(TRUE);
  149.                 KillTimer(ab_hwnd, HIDE_TIMER);
  150.             }
  151.             if (sys_vars.newshell) {
  152.                 abd.cbSize = sizeof(APPBARDATA);
  153.                 abd.hWnd = ab_hwnd;
  154.                 SHAppBarMessage(ABM_ACTIVATE, &abd);
  155.             }
  156.             return DefWindowProc(hWnd, msg, wParam, lParam);
  157.         case WM_NCMOUSEMOVE:
  158.             if (user_vars.autohide)
  159.                 if (!IsShown) {
  160.                     POINT pt;
  161.                     GetCursorPos(&pt);
  162.                 // Don't show AppBar if the mouse moves in the right 10% of the screen
  163.                 // this is so using the max/min buttons doesn't accidently uncover
  164.                 // AppBar.
  165.                     if (pt.x < (sys_vars.width - (int)(sys_vars.width/10)))
  166.                         HideAppBar(FALSE);
  167.                     timer = SetTimer(ab_hwnd, HIDE_TIMER, 500, NULL);
  168.                   } else {
  169.                     if (timer)
  170.                         KillTimer(ab_hwnd, HIDE_TIMER);
  171.                     timer = SetTimer(ab_hwnd, HIDE_TIMER, 500, NULL);
  172.                 }
  173.             return 0;
  174.         case WM_CLOSE:
  175.         case WM_QUIT:
  176. //        case WM_NCLBUTTONDBLCLK:
  177.             adam = GlobalFindAtom("AppBar HotKey");
  178.             UnregisterHotKey(ab_hwnd, adam);
  179.             GlobalDeleteAtom(adam);
  180.             exit_appbar(FALSE);
  181.             PostQuitMessage(0);
  182.             return 0;
  183.         case WM_COMMAND:
  184.             switch (LOWORD(wParam)) {
  185. /*              case ID_RUN:
  186.                     DialogBox(ab_inst, MAKEINTRESOURCE(IDD_RUN), ab_hwnd, (DLGPROC)RunProc);
  187.                     return 0; */
  188.                 case ID_EDIT:
  189.                     DialogBox(ab_inst, MAKEINTRESOURCE(IDD_EDIT), ab_hwnd, (DLGPROC)EditProc);
  190.                     return 0;
  191.                 case ID_ABOUT:
  192.                     DialogBox(ab_inst, MAKEINTRESOURCE(IDD_ABOUT), ab_hwnd, (DLGPROC)AboutProc);
  193.                     return 0;
  194.                 case ID_OPTIONS:
  195.                     DialogBox(ab_inst, MAKEINTRESOURCE(IDD_OPTIONS), ab_hwnd,(DLGPROC)OptionsProc);
  196.                     return 0;
  197.                 case ID_EXITAPPBAR:
  198.                     adam = GlobalFindAtom("AppBar HotKey");
  199.                     UnregisterHotKey(ab_hwnd, adam);
  200.                     GlobalDeleteAtom(adam);
  201.                     exit_appbar(FALSE);
  202.                     PostQuitMessage(0);
  203.                     return 0;
  204.                 default:
  205.                     find = find_appId((UINT)LOWORD(wParam));
  206.                     if (!find) return 0;
  207.                     execute_application(find);
  208.                     return 0;
  209.             }
  210. /*      case WM_APPBAR:
  211.             if ((wParam == ABN_FULLSCREENAPP) && user_vars.stayontop)
  212.                 SetWindowPos(ab_hwnd, (!lParam ? HWND_TOPMOST : HWND_NOTOPMOST),
  213.                                 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  214.             return 0; */
  215.         default:            
  216.             return DefWindowProc(hWnd, msg, wParam, lParam);
  217.     }
  218. }
  219.  
  220. // Returns app structure associated with a given menu ID
  221.  
  222. app_struct * find_appId(WPARAM menuId)
  223. {
  224.     app_list * temp;
  225.  
  226.     temp = applist;
  227.     while (temp->appId != (int)menuId) {
  228.         temp = temp->next;
  229.         if (temp == NULL)
  230.             return NULL;
  231.     }
  232.     return temp->app;
  233. }
  234.  
  235. // create and show the appbar window
  236.  
  237. BOOL show_appbar(void)
  238. {
  239.     int flags = (user_vars.stayontop ? WS_EX_TOPMOST : 0) | WS_EX_TOOLWINDOW;
  240.     ab_hwnd = CreateWindowEx(flags,"ABClass", "AppBar", WS_POPUP | WS_DLGFRAME, 0, 
  241.                 (user_vars.bottom ? sys_vars.height - AB_HEIGHT : 0),
  242.                 AB_WIDTH, AB_HEIGHT, 0, 0, ab_inst, 0);
  243.  
  244.     if (!ab_hwnd)
  245.         return FALSE;
  246.     
  247.     if (sys_vars.newshell) {
  248.         BOOL ab;
  249.         abd.cbSize = sizeof(APPBARDATA);
  250.         abd.hWnd = ab_hwnd;
  251.         abd.uCallbackMessage = NULL; //WM_APPBAR;
  252.         abd.uEdge = (user_vars.bottom ? ABE_BOTTOM : ABE_TOP);
  253.         ab = SHAppBarMessage(ABM_NEW, &abd);
  254.         if (ab && user_vars.autohide) {
  255.             abd.lParam = TRUE;
  256.             if (!SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd)) {
  257.                 ab_message(ERROR_AUTOHIDING);
  258.                 user_vars.autohide = FALSE;
  259.             }
  260.         } else if (ab) {
  261.             abd.rc.top = 0;
  262.             abd.rc.left = 0;
  263.             abd.rc.right = GetSystemMetrics(SM_CXSCREEN);
  264.             abd.rc.bottom = GetSystemMetrics(SM_CYSCREEN);
  265.             SHAppBarMessage(ABM_QUERYPOS, &abd);
  266.             abd.rc.top = (user_vars.bottom ? abd.rc.bottom - AB_HEIGHT : abd.rc.top);
  267.             MoveWindow(ab_hwnd, abd.rc.left, abd.rc.top, AB_WIDTH, AB_HEIGHT, TRUE);
  268.             abd.rc.bottom = abd.rc.top + AB_HEIGHT;
  269.             abd.rc.right = AB_WIDTH;
  270.             SHAppBarMessage(ABM_SETPOS, &abd);
  271.         }
  272.     }
  273.         // Insert applications into window menu
  274.     update_menus();
  275.     ShowWindow(ab_hwnd, SW_SHOW);
  276.     if (sys_vars.newshell) 
  277.         if (user_vars.autohide)
  278.             HideAppBar(TRUE);
  279.           else
  280.             modify_time();
  281.       else
  282.         HideAppBar(TRUE);
  283.     return TRUE;
  284. }
  285.  
  286. void update_menus(void)
  287. {
  288.     int a=1, m=1;
  289.     app_struct *app;
  290.     menu_struct *menu, *firstapp;
  291.     HMENU hmenu;
  292.     app_list *curapplist, *prevapplist;
  293.  
  294.     kill_applist();
  295.     DestroyMenu(ab_menu);
  296.     
  297.     ab_menu = CreateMenu();
  298.     SetMenu(ab_hwnd, ab_menu);
  299.  
  300.     if (!glob_menu) {
  301.         applist = NULL;
  302.         DrawMenuBar(ab_hwnd);
  303.         modify_time();
  304.         return;
  305.     }
  306.  
  307.     for (menu = glob_menu, firstapp = NULL; menu; menu = menu->nextmenu)
  308.         if (menu->nextapp) {
  309.             firstapp = menu;
  310.             break;
  311.         }
  312.  
  313.     for (menu = glob_menu; menu; menu = menu->nextmenu) {
  314.         hmenu = CreateMenu();
  315.         for (app = menu->nextapp; app; app = app->nextapp) {
  316.             if (app->separator)                 // Put in separator
  317.                 AppendMenu(hmenu, MF_SEPARATOR, 0, 0);
  318.             AppendMenu(hmenu, MF_STRING, (m*100 + a), app->appname);
  319.             if (firstapp->nextapp == app) {
  320.                 applist = new app_list;
  321.                 curapplist = applist;
  322.               } else {
  323.                 curapplist = new app_list;
  324.                 prevapplist->next = curapplist;
  325.             }
  326.             curapplist->appId = m*100 + a;
  327.             curapplist->app = app;                              
  328.             curapplist->next = NULL;
  329.             prevapplist = curapplist;
  330.             a++;
  331.         }
  332.         InsertMenu(ab_menu, m, MF_BYPOSITION | MF_POPUP, (UINT)hmenu, menu->menuname);
  333.         a = 1;
  334.         m++;
  335.     }
  336.     DrawMenuBar(ab_hwnd);
  337.     return;
  338. }
  339.  
  340. // hides or shows AppBar, depending on "hide" variable
  341.  
  342. void HideAppBar(BOOL hide)
  343. {
  344.     int newy;
  345.     BOOL drag = TRUE;
  346.  
  347.     if (!hide && IsShown)
  348.         return;
  349.  
  350.     if (sys_vars.newshell)
  351.         SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &drag, 0);
  352.  
  353.     if (hide) {
  354.         newy = (user_vars.bottom ? sys_vars.height - 2 : -(AB_HEIGHT - 2));
  355.         if (drag)
  356.             SlideWindow(newy);
  357.           else
  358.             SetWindowPos(ab_hwnd, NULL, 0, newy, AB_WIDTH,
  359.                         AB_HEIGHT, SWP_NOACTIVATE | SWP_NOZORDER);
  360.         IsShown = FALSE;
  361.     } else {
  362.         newy = (user_vars.bottom ? sys_vars.height - AB_HEIGHT : 0);
  363.         if (drag)
  364.             SlideWindow(newy);
  365.           else
  366.             SetWindowPos(ab_hwnd, NULL, 0, newy, AB_WIDTH, AB_HEIGHT,
  367.                         SWP_NOACTIVATE | SWP_NOZORDER);
  368.         IsShown = TRUE;
  369.         modify_time();
  370.     }
  371. }
  372.  
  373. // draws arrow buttons in edit box
  374.  
  375. void draw_buttons(DRAWITEMSTRUCT *dw, UINT CtlID)
  376. {
  377.     // these icons will be loaded once only (because they are static)
  378.     static HICON up1   = (HICON) LoadImage(ab_inst, MAKEINTRESOURCE(IDI_UP1), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  379.     static HICON down1 = (HICON) LoadImage(ab_inst, MAKEINTRESOURCE(IDI_DOWN1), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  380.     static HICON up2   = (HICON) LoadImage(ab_inst, MAKEINTRESOURCE(IDI_UP2), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  381.     static HICON down2 = (HICON) LoadImage(ab_inst, MAKEINTRESOURCE(IDI_DOWN2), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  382.  
  383.     if ((CtlID == IDB_APPUP) || (CtlID == IDB_MENUUP)) {
  384.         if (dw->itemState & ODS_SELECTED)
  385.             DrawIconEx(dw->hDC, 0, 0, up2, 16, 16, NULL, NULL, DI_NORMAL);
  386.           else 
  387.             DrawIconEx(dw->hDC, 0, 0, up1, 16, 16, NULL, NULL, DI_NORMAL);
  388.         return;
  389.       } else if ((CtlID == IDB_APPDOWN) || (CtlID == IDB_MENUDOWN)) {
  390.         if (dw->itemState & ODS_SELECTED)
  391.             DrawIconEx(dw->hDC, 0, 0, down2, 16, 16, NULL, NULL, DI_NORMAL);
  392.           else 
  393.             DrawIconEx(dw->hDC, 0, 0, down1, 16, 16, NULL, NULL, DI_NORMAL);
  394.         return;
  395.     }
  396. }
  397.  
  398.  
  399. // MAX(a,b) was causing a bug in AppBar because I was in-line decrementing so it would expand to:
  400. // ((--a>b) ? (--a) : b) because it is a macro, not a function.
  401. //
  402. // I just wanted: ((--a>b) ? (a) : (b))
  403.  
  404. inline int mymax(int a, int b)
  405. {
  406.     return ((a>b) ? a : b);
  407. }
  408.  
  409. inline int mymin(int a, int b)
  410. {
  411.     return ((a>b) ? b : a);
  412. }
  413.  
  414.  
  415. LRESULT CALLBACK EditProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  416. {
  417.     char menu_sel[30],
  418.          app_sel[30];
  419.     menu_struct *menus, *newmenu;
  420.     app_struct *apps, *newapp;
  421.     int index;
  422.     int i;
  423.     BOOL sep, flag;
  424.     hack Hack;
  425.     
  426.     switch (message) {              // this is the mother of all switch statements
  427.         case WM_INITDIALOG:         // Fill menu list with current menus
  428.             EditDlg = hDlg;
  429.             for (menus = glob_menu; menus; menus = menus->nextmenu)
  430.                 SendDlgItemMessage(hDlg, IDC_MENULIST, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)((LPSTR)menus->menuname));
  431.             menus = glob_menu;
  432.             DragAcceptFiles(GetDlgItem(EditDlg, IDC_MENULIST), TRUE);
  433.             EnableWindow(GetDlgItem(EditDlg, IDB_DELMENU), FALSE);
  434.             EnableWindow(GetDlgItem(EditDlg, IDB_DELAPP), FALSE);
  435.             EnableWindow(GetDlgItem(EditDlg, IDB_SEPARATOR), FALSE);
  436.             return TRUE;
  437.         case WM_DRAWITEM:
  438.             draw_buttons((DRAWITEMSTRUCT*)lParam, (UINT)wParam);
  439.             return TRUE;
  440.         case WM_DROPFILES:
  441.             HDROP hd;
  442.             RECT r;
  443.             POINT p;
  444.             div_t dt;
  445.             int m, width;
  446.             char *last_slash, *last_period, *name;
  447.  
  448.             hd = (HDROP) wParam;
  449.             m = DragQueryFile(hd, 0xFFFFFFFF, 0, 0);
  450.             DragQueryPoint(hd, &p);
  451.             SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETITEMRECT, 0, (LPARAM)&r);
  452.             width = r.bottom - r.top;
  453.             dt = div(p.y, width);
  454.             dt.quot += SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETTOPINDEX, 0, 0);
  455.             menus = glob_menu;
  456.             if (!menus) {DragFinish(hd); return TRUE;}
  457.             for (i=0;i<dt.quot;i++) {
  458.                 if (menus->nextmenu)
  459.                     menus = menus->nextmenu;
  460.                   else {DragFinish(hd); return TRUE;}
  461.             }
  462.             while (m--) {
  463.                 apps = menus->nextapp;
  464.                 if (apps)
  465.                     while (apps->nextapp)
  466.                         apps = apps->nextapp;
  467.                 if (apps) {
  468.                     apps->nextapp = new app_struct;
  469.                     apps->nextapp->prevapp = apps;
  470.                     apps = apps->nextapp;
  471.                   } else {
  472.                     menus->nextapp = new app_struct;
  473.                     menus->nextapp->prevapp = NULL;
  474.                     apps = menus->nextapp;
  475.                 }
  476.                 DragQueryFile(hd, m, apps->appexe, sizeof(apps->appexe));
  477.                 last_slash = strrchr(apps->appexe, 0x5C);  // backslash
  478.                 last_period = strrchr(apps->appexe, 0x2E); // period
  479.                 if (!last_slash) last_slash = (char *) apps->appexe;
  480.                 if (!last_period)
  481.                     strcpy(apps->appname, last_slash);
  482.                   else { 
  483.                     last_slash++;
  484.                     name = (char *) apps->appname;
  485.                     while (last_slash != last_period) {
  486.                         *last_slash = tolower(*last_slash);
  487.                         *name++ = *last_slash++;
  488.                     }
  489.                 }
  490.                 apps->appname[0] = (char) toupper((int)apps->appname[0]);
  491.                 if (!strcmp(apps->appname, ""))
  492.                     strcpy(apps->appname, DEFAULT_NAME);
  493.                 menus->numapps++;
  494.  
  495.                 char drive[40], path[80];
  496.                 _splitpath(apps->appexe, drive, path, NULL, NULL);
  497.                 sprintf(apps->workingdir, "%s%s", drive, path);
  498.                 int len = strlen(apps->workingdir);
  499.                 // we don't want to remove the \ in c:\
  500.                 if (len>3)
  501.                     // remove trailing backslash on directory
  502.                     *(apps->workingdir + len - 1) = '\0';
  503.                 SendDlgItemMessage(hDlg, IDC_MENULIST, LB_SETCURSEL, i, 0);
  504.                 SetFocus(GetDlgItem(hDlg, IDC_MENULIST));
  505.             }
  506.             DragFinish(hd);
  507.             return TRUE;
  508.         case WM_COMMAND:
  509.             switch LOWORD(wParam) {
  510.                 case IDOK:
  511.                     save_menus();
  512.                     update_menus();
  513.                     modify_time();
  514.                     EndDialog(hDlg, TRUE);
  515.                     return TRUE;
  516.                 case IDC_MENULIST:      // User selected a menu, get menu and show related apps
  517.                     if (HIWORD(wParam)==LBN_SELCHANGE) {
  518.                         EnableWindow(GetDlgItem(EditDlg, IDB_DELMENU), TRUE);
  519.                         index = SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETCURSEL, 0, 0);
  520.                         SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETTEXT,(WPARAM) index,(LPARAM)((LPSTR) menu_sel));
  521.                         menus = find_menu(menu_sel);
  522.                         if (!menus) return FALSE;
  523.                         // Found correct menu, now fill other listbox with apps
  524.                         SendDlgItemMessage(hDlg, IDC_APPLIST, LB_RESETCONTENT, 0,0);
  525.                         for (apps = menus->nextapp; apps; apps = apps->nextapp) {
  526.                             if (apps->separator)
  527.                                 SendDlgItemMessage(hDlg, IDC_APPLIST, LB_ADDSTRING, 0, (LPARAM)((LPSTR) SEPARATOR_STRING));
  528.                             SendDlgItemMessage(hDlg, IDC_APPLIST, LB_ADDSTRING, 0, (LPARAM)((LPSTR) apps->appname));
  529.                         }
  530.                       } else if (HIWORD(wParam) == LBN_DBLCLK) {
  531.                             index = SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETCURSEL, 0, 0);
  532.                             if (index == LB_ERR) {ab_message(SELECT_MENU);return 0;}
  533.                             SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETTEXT,(WPARAM) index,(LPARAM)((LPSTR) menu_sel));
  534.                             menus = find_menu(menu_sel);
  535.                             if (!menus) return FALSE;
  536.                             Hack.isnew = FALSE;
  537.                             Hack.app = NULL;
  538.                             Hack.menu = menus;
  539.                             DialogBoxParam(ab_inst, MAKEINTRESOURCE(IDD_NEWMENU), hDlg, (DLGPROC) MenuProc, (LPARAM)&Hack);
  540.                             SendDlgItemMessage(hDlg, IDC_MENULIST, LB_SETCURSEL, index, 0);
  541.                       }
  542.                     return FALSE;
  543.                 case IDC_APPLIST:
  544.                     if (HIWORD(wParam)==LBN_DBLCLK) {
  545.                         menus = glob_menu;
  546.                         index = SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETCURSEL, 0, 0);
  547.                         if (index == LB_ERR) {ab_message(SELECT_MENU);return TRUE;}
  548.                         SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETTEXT,(WPARAM) index,(LPARAM)((LPSTR) menu_sel));
  549.                         menus = find_menu(menu_sel);
  550.                         if (!menus) return FALSE;
  551.                         apps = menus->nextapp;
  552.                         index = SendDlgItemMessage(hDlg, IDC_APPLIST, LB_GETCURSEL, 0, 0);
  553.                         SendDlgItemMessage(hDlg, IDC_APPLIST, LB_GETTEXT,(WPARAM) index,(LPARAM)((LPSTR) app_sel));
  554.                         apps = find_app(apps, app_sel);
  555.                         if (!apps) return FALSE;
  556.                         Hack.app = apps;
  557.                         Hack.isnew = FALSE;
  558.                         Hack.menu = menus;
  559.                         DialogBoxParam(ab_inst, MAKEINTRESOURCE(IDD_NEWAPP), hDlg, (DLGPROC) AppProc, (LPARAM)&Hack);
  560.                         SendDlgItemMessage(hDlg, IDC_APPLIST, LB_SETCURSEL, index, 0);
  561.                         return FALSE;
  562.                       } else if (HIWORD(wParam)==LBN_SELCHANGE) {
  563.                         EnableWindow(GetDlgItem(EditDlg, IDB_DELAPP), TRUE);
  564.                         EnableWindow(GetDlgItem(EditDlg, IDB_SEPARATOR), TRUE);
  565.                     }
  566.                     return FALSE;
  567.                 case IDB_NEWMENU:
  568.                     newmenu = glob_menu;
  569.                     if (newmenu)
  570.                         while (newmenu->nextmenu)
  571.                             newmenu = newmenu->nextmenu;
  572.                     Hack.isnew = TRUE;
  573.                     Hack.app = NULL;
  574.                     Hack.menu = newmenu;
  575.                     DialogBoxParam(ab_inst, MAKEINTRESOURCE(IDD_NEWMENU), hDlg, (DLGPROC)MenuProc, (LRESULT)&Hack);
  576.                     return FALSE;
  577.                 case IDB_NEWAPP:
  578.                     index = SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETCURSEL, 0, 0);
  579.                     if (index == LB_ERR) {ab_message(SELECT_MENU);return 0;}
  580.                     SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETTEXT, (WPARAM)index, (LPARAM)((LPSTR)menu_sel));
  581.                     menus = find_menu(menu_sel);
  582.                     if (!menus) return FALSE;
  583.                     newapp = menus->nextapp;
  584.                     if (newapp)
  585.                         while (newapp->nextapp)
  586.                             newapp = newapp->nextapp;
  587.                     Hack.isnew = TRUE;
  588.                     Hack.app = newapp;
  589.                     Hack.menu = menus;
  590.                     DialogBoxParam(ab_inst, MAKEINTRESOURCE(IDD_NEWAPP), hDlg, (DLGPROC)AppProc, (LPARAM)&Hack);
  591.                     return FALSE;
  592.                 case IDB_DELMENU:
  593.                     index = SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETCURSEL, 0, 0);
  594.                     if (index == LB_ERR) {ab_message(SELECT_MENU);return 0;}
  595.                     SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETTEXT, (WPARAM)index, (LPARAM)((LPSTR)menu_sel));
  596.                     menus = find_menu(menu_sel);
  597.                     if (!menus) return FALSE;
  598.                     i = MessageBox(hDlg, CONFIRM_DELETE, CONFIRM_DELETE_TITLE, MB_YESNO);
  599.                     if (i == IDYES) {
  600.                         killmenu(menus);
  601.                         SendDlgItemMessage(hDlg, IDC_MENULIST, LB_DELETESTRING, (WPARAM)index, 0);
  602.                         SendDlgItemMessage(hDlg, IDC_APPLIST, LB_RESETCONTENT, 0, 0);
  603.                     }
  604.                     SetFocus(GetDlgItem(EditDlg, IDC_MENULIST));
  605.                     SendDlgItemMessage(hDlg, IDC_MENULIST, LB_SETCURSEL, (WPARAM) index, 0);
  606.                     return FALSE;
  607.                 case IDB_DELAPP:
  608.                     index = SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETCURSEL, 0, 0);
  609.                     if (index == LB_ERR) {ab_message(SELECT_MENU);return 0;}
  610.                     SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETTEXT, (WPARAM)index, (LPARAM)((LPSTR)menu_sel));
  611.                     menus = find_menu(menu_sel);
  612.                     if (!menus) return FALSE;
  613.                     index = SendDlgItemMessage(hDlg, IDC_APPLIST, LB_GETCURSEL, 0, 0);
  614.                     if (index == LB_ERR) {ab_message(SELECT_ITEM);return 0;}
  615.                     sep = FALSE;  // whether we should delete the separator
  616.                     SendDlgItemMessage(hDlg, IDC_APPLIST, LB_GETTEXT, (WPARAM)index, (LPARAM)((LPSTR)app_sel));
  617.                     if (!strcmp(app_sel,SEPARATOR_STRING))  {   // User wants to delete a separator
  618.                         SendDlgItemMessage(hDlg, IDC_APPLIST, LB_GETTEXT, (WPARAM)++index, (LPARAM)((LPSTR)app_sel));
  619.                         index--;
  620.                         sep = TRUE;
  621.                     }
  622.                     apps = menus->nextapp;
  623.                     apps = find_app(apps, app_sel);
  624.                     if (!apps) return FALSE;
  625.                     if (sep)    // If we are deleting sep, just reset variable
  626.                         apps->separator = FALSE;
  627.                       else {    // else kill app structure
  628.                           // if the app has a separator, we need to delete it from the listbox too
  629.                         if (apps->separator) {
  630.                             SendDlgItemMessage(hDlg, IDC_APPLIST, LB_DELETESTRING, --index, 0);
  631.                             flag = TRUE;
  632.                         }
  633.                         if (menus->nextapp == apps)
  634.                             menus->nextapp = apps->nextapp;
  635.                         killapp(apps);
  636.                         menus->numapps--;
  637.                     }
  638.                     SendDlgItemMessage(hDlg, IDC_APPLIST, LB_DELETESTRING, (WPARAM)index, 0);
  639.                     SetFocus(GetDlgItem(EditDlg, IDC_APPLIST));
  640.                     if (flag) index--;
  641.                     SendDlgItemMessage(hDlg, IDC_APPLIST, LB_SETCURSEL, (WPARAM) index, 0);
  642.                     return FALSE;
  643.                 case IDB_SEPARATOR:
  644.                     index = SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETCURSEL, 0, 0);
  645.                     if (index == LB_ERR) {ab_message(SELECT_MENU);return 0;}
  646.                     SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETTEXT, (WPARAM)index, (LPARAM)((LPSTR)menu_sel));
  647.                     menus = find_menu(menu_sel);
  648.                     if (!menus) return FALSE;
  649.                     index = SendDlgItemMessage(hDlg, IDC_APPLIST, LB_GETCURSEL, 0, 0);
  650.                     if (index == LB_ERR) {ab_message(SELECT_ITEM);return 0;}
  651.                     SendDlgItemMessage(hDlg, IDC_APPLIST, LB_GETTEXT, (WPARAM)index, (LPARAM)((LPSTR)app_sel));
  652.                     apps = menus->nextapp;
  653.                     apps = find_app(apps, app_sel);
  654.                     if (!apps) return FALSE;
  655.                     if (apps->separator) return FALSE;  // Can't add a second separator!
  656.                     apps->separator = TRUE;
  657.                     SendDlgItemMessage(hDlg, IDC_APPLIST, LB_INSERTSTRING, (WPARAM)index, (LPARAM)((LPSTR)SEPARATOR_STRING));
  658.                     return FALSE;
  659.                 case IDB_MENUDOWN:
  660.                 case IDB_MENUUP:
  661.                     index = SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETCURSEL, 0, 0);
  662.                     if (index == LB_ERR) {ab_message(SELECT_MENU);return 0;}
  663.                     SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETTEXT, (WPARAM)index, (LPARAM)((LPSTR)menu_sel));
  664.                     menus = find_menu(menu_sel);
  665.                     if (!menus) return FALSE;
  666.                     if (LOWORD(wParam) == IDB_MENUDOWN)
  667.                         switch_places_m(menus, DOWN);
  668.                       else
  669.                         switch_places_m(menus, UP);
  670.                     SendDlgItemMessage(hDlg, IDC_MENULIST, LB_RESETCONTENT, 0, 0);
  671.                     for (menus = glob_menu; menus; menus = menus->nextmenu)
  672.                         SendDlgItemMessage(hDlg, IDC_MENULIST, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)((LPSTR)menus->menuname));
  673.                     SetFocus(GetDlgItem(EditDlg, IDC_MENULIST));
  674.                     i = SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETCOUNT, 0, 0);
  675.                     SendDlgItemMessage(hDlg, IDC_MENULIST, LB_SETCURSEL, (WPARAM) (LOWORD(wParam)==IDB_MENUUP ? mymax(0, --index) : mymin(--i, ++index)), 0);
  676.                     return FALSE;
  677.                 case IDB_APPDOWN:
  678.                 case IDB_APPUP:
  679.                     menus = glob_menu;
  680.                     index = SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETCURSEL, 0, 0);
  681.                     if (index == LB_ERR) {ab_message(SELECT_MENU);return TRUE;}
  682.                     SendDlgItemMessage(hDlg, IDC_MENULIST, LB_GETTEXT,(WPARAM) index,(LPARAM)((LPSTR) menu_sel));
  683.                     menus = find_menu(menu_sel);
  684.                     if (!menus) return FALSE;
  685.                     apps = menus->nextapp;
  686.                     index = SendDlgItemMessage(hDlg, IDC_APPLIST, LB_GETCURSEL, 0, 0);
  687.                     if (index == LB_ERR) {ab_message(SELECT_ITEM);return TRUE;}
  688.                     SendDlgItemMessage(hDlg, IDC_APPLIST, LB_GETTEXT,(WPARAM) index,(LPARAM)((LPSTR) app_sel));
  689.                     apps = find_app(apps, app_sel);
  690.                     if (!apps) return FALSE;
  691.                     if ((LOWORD(wParam)) == IDB_APPUP) {    // move over separators...
  692.                         if (apps->prevapp)
  693.                             if (apps->prevapp->separator)
  694.                                 index--;
  695.                     } else {
  696.                         if (apps->nextapp)
  697.                             if (apps->nextapp->separator)
  698.                                 index++;
  699.                     }
  700.                     if (LOWORD(wParam) == IDB_APPDOWN) {
  701.                         if (menus->nextapp == apps)
  702.                             menus->nextapp = menus->nextapp->nextapp;
  703.                         switch_places_a(apps, DOWN);
  704.                       } else {
  705.                         if (menus->nextapp->nextapp)
  706.                             if (menus->nextapp->nextapp == apps)
  707.                                 menus->nextapp = menus->nextapp->nextapp;
  708.                         switch_places_a(apps, UP);
  709.                     }
  710.                     SendDlgItemMessage(hDlg, IDC_APPLIST, LB_RESETCONTENT, 0, 0);
  711.                     for (apps = menus->nextapp; apps; apps = apps->nextapp) {
  712.                         if (apps->separator) 
  713.                             SendDlgItemMessage(hDlg, IDC_APPLIST, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)((LPSTR)SEPARATOR_STRING));
  714.                         SendDlgItemMessage(hDlg, IDC_APPLIST, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)((LPSTR)apps->appname));
  715.                     }
  716.                     SetFocus(GetDlgItem(EditDlg, IDC_APPLIST));
  717.                     i = SendDlgItemMessage(hDlg, IDC_APPLIST, LB_GETCOUNT, 0, 0);
  718.                     SendDlgItemMessage(hDlg, IDC_APPLIST, LB_SETCURSEL, (WPARAM) (LOWORD(wParam)==IDB_APPUP ? mymax(0, --index) : mymin(--i, ++index)), 0);
  719.                     return FALSE;
  720.                 default:
  721.                     return FALSE;
  722.             }
  723.         default:
  724.             return FALSE;
  725.     }
  726. }
  727.  
  728. LRESULT CALLBACK MenuProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  729. {           
  730.     static menu_struct *newmenu;
  731.     static BOOL isnew = FALSE;
  732.     static int index;
  733.     static hack * phack;
  734.  
  735.     switch (message) {
  736.         case WM_INITDIALOG:
  737.             phack = (hack *) lParam;
  738.             newmenu = phack->menu;
  739.             isnew = phack->isnew;
  740.             if (isnew)
  741.                 if (newmenu) {
  742.                     newmenu->nextmenu = new menu_struct;
  743.                     newmenu->nextmenu->prevmenu = newmenu;
  744.                     newmenu = newmenu->nextmenu;
  745.                   } else {
  746.                     glob_menu = new menu_struct;
  747.                     newmenu = glob_menu;
  748.                 }
  749.             SetFocus(GetDlgItem(hDlg, IDC_MENUNAME));
  750.             SendMessage(GetDlgItem(hDlg, IDC_MENUNAME), WM_SETTEXT, 0, (LPARAM)newmenu->menuname);
  751.             index = SendDlgItemMessage(EditDlg,IDC_MENULIST, LB_GETCURSEL, 0, 0);
  752.             return FALSE;
  753.         case WM_COMMAND:
  754.             if (wParam == IDOK) {
  755.                 char buffer[30];
  756.  
  757.                 SendMessage(GetDlgItem(hDlg, IDC_MENUNAME), WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
  758.                 if (!strcmp(buffer,"")) {
  759.                     ab_message(ERROR_MENUNAME);
  760.                     return TRUE;
  761.                 }
  762.                 strcpy(newmenu->menuname, buffer);
  763.                 if (!isnew) {
  764.                     SendDlgItemMessage(EditDlg, IDC_MENULIST, LB_DELETESTRING,  index, 0);
  765.                     SendDlgItemMessage(EditDlg, IDC_MENULIST, LB_INSERTSTRING, index, (LPARAM) (LPCSTR)newmenu->menuname);
  766.                   } else
  767.                     SendDlgItemMessage(EditDlg, IDC_MENULIST, LB_INSERTSTRING, (WPARAM)-1, (LPARAM) (LPCSTR)newmenu->menuname);
  768.                 EndDialog(hDlg, TRUE);
  769.                 return TRUE;
  770.               } else if (wParam==IDCANCEL) {
  771.                 if (isnew) {
  772.                     delete newmenu;
  773.                     phack->menu->nextmenu = NULL;
  774.                 }
  775.                 EndDialog(hDlg, TRUE);
  776.                 return TRUE;
  777.             }                           
  778.         default:
  779.             return FALSE;
  780.     }
  781. }
  782.  
  783. LRESULT CALLBACK AppProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  784. {
  785.     static app_struct *pnewapp;
  786.     static menu_struct *menu;
  787.     static BOOL isnew = FALSE;
  788.     static hack *phack;
  789.     static int index;
  790.     int check_button;
  791.             
  792.     switch (message) {    
  793.         case WM_INITDIALOG:
  794.             phack = (hack *) lParam;        // hack is a hack so that I can pass two 32-bit
  795.             isnew = phack->isnew;           // pointers with one 32-bit pointer
  796.             if (isnew) {
  797.                 menu = phack->menu;
  798.                 pnewapp = new app_struct;
  799.               } else 
  800.                 pnewapp = phack->app;
  801.             switch (pnewapp->show) {
  802.                 case SW_MAXIMIZE:
  803.                     check_button = IDC_MAX;
  804.                     break;
  805.                 case SW_MINIMIZE:
  806.                     check_button = IDC_MIN;
  807.                     break;
  808.                 default:
  809.                     check_button = IDC_NORMAL;
  810.                     break;
  811.             }
  812.             CheckRadioButton(hDlg, IDC_NORMAL, IDC_MIN, check_button);
  813.             index = SendDlgItemMessage(EditDlg,IDC_APPLIST, LB_GETCURSEL, 0, 0);
  814.             SendMessage(GetDlgItem(hDlg, IDC_EXENAME), WM_SETTEXT, 0, (LPARAM)pnewapp->appexe);
  815.             SendMessage(GetDlgItem(hDlg, IDC_APPNAME), WM_SETTEXT, 0, (LPARAM)pnewapp->appname);
  816.             SendMessage(GetDlgItem(hDlg, IDC_WORKINGDIR), WM_SETTEXT, 0, (LPARAM)pnewapp->workingdir);
  817.             SendMessage(GetDlgItem(hDlg, IDC_PARAMETERS), WM_SETTEXT, 0, (LPARAM)pnewapp->params);
  818.             SetFocus(GetDlgItem(hDlg, IDC_APPNAME));
  819.             return FALSE;
  820.         case WM_COMMAND:
  821.             if (wParam==IDOK) {
  822.                 char buf1[80], buf2[30];
  823.                 SendMessage(GetDlgItem(hDlg, IDC_EXENAME), WM_GETTEXT, sizeof(buf1), (LPARAM)buf1);
  824.                 SendMessage(GetDlgItem(hDlg, IDC_APPNAME), WM_GETTEXT, sizeof(buf2), (LPARAM)buf2);
  825.                 if ((!strcmp(buf1, "")) || (!strcmp(buf2, ""))) {
  826.                     ab_message(ERROR_NAME_FILENAME);
  827.                     return TRUE;
  828.                 }
  829.                 SendMessage(GetDlgItem(hDlg, IDC_EXENAME), WM_GETTEXT, sizeof(pnewapp->appexe), (LPARAM)pnewapp->appexe);
  830.                 SendMessage(GetDlgItem(hDlg, IDC_APPNAME), WM_GETTEXT, sizeof(pnewapp->appname), (LPARAM)pnewapp->appname);
  831.                 SendMessage(GetDlgItem(hDlg, IDC_PARAMETERS), WM_GETTEXT, sizeof(pnewapp->params), (LPARAM)pnewapp->params);
  832.                 SendMessage(GetDlgItem(hDlg, IDC_WORKINGDIR), WM_GETTEXT, sizeof(pnewapp->workingdir), (LPARAM)pnewapp->workingdir);
  833.                 if (!strcmp(pnewapp->workingdir, "")) {
  834.                     char drive[4], path[80];
  835.                     _splitpath(pnewapp->appexe, drive, path, NULL, NULL);
  836.                     sprintf(pnewapp->workingdir, "%s%s", drive, path);
  837.                     int len = strlen(pnewapp->workingdir);
  838.                     // we don't want to remove the \ in c:\
  839.                     if (len>3)
  840.                         // remove trailing backslash on directory
  841.                         *(pnewapp->workingdir + len - 1) = '\0';
  842.                 }
  843.                 if (IsDlgButtonChecked(hDlg, IDC_NORMAL))
  844.                     pnewapp->show = SW_RESTORE;
  845.                   else if (IsDlgButtonChecked(hDlg, IDC_MAX))
  846.                     pnewapp->show = SW_MAXIMIZE;
  847.                   else if (IsDlgButtonChecked(hDlg, IDC_MIN))
  848.                     pnewapp->show = SW_MINIMIZE;
  849.                 if (isnew) {
  850.                     if (phack->app) {
  851.                         phack->app->nextapp = pnewapp;
  852.                         pnewapp->prevapp = phack->app;
  853.                       } else {          // first app in menu
  854.                         phack->menu->nextapp = pnewapp;
  855.                         pnewapp->prevapp = NULL;
  856.                     }
  857.                     menu->numapps++;
  858.                     SendDlgItemMessage(EditDlg, IDC_APPLIST, LB_INSERTSTRING, (WPARAM) -1, (LPARAM)pnewapp->appname);
  859.                   } else {
  860.                     SendDlgItemMessage(EditDlg, IDC_APPLIST, LB_DELETESTRING, index, 0);
  861.                     SendDlgItemMessage(EditDlg, IDC_APPLIST, LB_INSERTSTRING, index, (LPARAM)pnewapp->appname);
  862.                 }
  863.                 EndDialog(hDlg, TRUE);
  864.                 return TRUE;
  865.             } else if (wParam==IDCANCEL) {
  866.                 if (isnew)
  867.                     delete pnewapp;
  868.                 EndDialog(hDlg, TRUE);
  869.                 return TRUE;
  870.             } else if (wParam == IDC_BROWSE) {
  871.                 DoBrowse(0, hDlg);
  872.                 return FALSE;
  873.         }
  874.         default:
  875.             return FALSE;
  876.     }   
  877. }
  878.  
  879. LRESULT CALLBACK OptionsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  880. {
  881.     char buffer[80];
  882.  
  883.     switch (message) {
  884.         case WM_INITDIALOG:
  885.             SendMessage(GetDlgItem(hDlg, IDC_WAVNAME), WM_SETTEXT, 0, (LPARAM)user_vars.wavfile);
  886.             CheckDlgButton(hDlg, IDC_CHIME, user_vars.chime);
  887.             CheckDlgButton(hDlg, IDC_DATE, user_vars.date);
  888.             CheckDlgButton(hDlg, IDC_MEMORY, user_vars.memory);
  889.             CheckDlgButton(hDlg, IDC_STAYONTOP, user_vars.stayontop);
  890.             CheckDlgButton(hDlg, IDC_BOTTOM, user_vars.bottom);
  891.             CheckDlgButton(hDlg, IDC_AUTOHIDE, user_vars.autohide);
  892.             CheckDlgButton(hDlg, IDC_TIME, user_vars.time);
  893.             CheckDlgButton(hDlg, IDC_USER, user_vars.user);
  894.             return TRUE;
  895.         case WM_COMMAND:
  896.             if (wParam == IDOK) {
  897.                 SendMessage(GetDlgItem(hDlg, IDC_WAVNAME), WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
  898.                 if (!strcmp(buffer, "") && user_vars.chime) {
  899.                     ab_message(ERROR_ENTER_WAVNAME);
  900.                     return FALSE;
  901.                 }
  902.                 strcpy(user_vars.wavfile, buffer);
  903.                 EndDialog(hDlg, TRUE);
  904.                 return TRUE;
  905.             } else if (HIWORD(wParam) == BN_CLICKED) {
  906.  
  907.                 switch (LOWORD(wParam)) {
  908.                     case IDC_DATE:
  909.                         user_vars.date = !user_vars.date;
  910.                         CheckDlgButton(hDlg, IDC_DATE, user_vars.date);
  911.                         modify_time();
  912.                         return FALSE;
  913.                     case IDC_USER:
  914.                         user_vars.user = !user_vars.user;
  915.                         CheckDlgButton(hDlg, IDC_USER, user_vars.user);
  916.                         modify_time();
  917.                         return FALSE;
  918.                     case IDC_TIME:
  919.                         user_vars.time = !user_vars.time;
  920.                         CheckDlgButton(hDlg, IDC_TIME, user_vars.time);
  921.                         modify_time();
  922.                         return FALSE;
  923.                     case IDC_MEMORY:
  924.                         user_vars.memory = !user_vars.memory;
  925.                         CheckDlgButton(hDlg, IDC_MEMORY, user_vars.memory);
  926.                         modify_time();
  927.                         return FALSE;
  928.                     case IDC_CHIME:
  929.                         user_vars.chime = !user_vars.chime;
  930.                         CheckDlgButton(hDlg, IDC_CHIME, user_vars.chime);
  931.                         return FALSE;
  932.                     case IDC_AUTOHIDE:
  933.                         if (sys_vars.newshell) {
  934.                             user_vars.autohide = !user_vars.autohide;
  935.                             CheckDlgButton(hDlg, IDC_AUTOHIDE, user_vars.autohide);
  936.                             // set or unset the autohide bar for this edge
  937.                             abd.cbSize = sizeof(APPBARDATA);
  938.                             abd.hWnd = ab_hwnd;
  939.                             abd.uEdge = (user_vars.bottom ? ABE_BOTTOM : ABE_TOP);
  940.                             abd.lParam = (user_vars.autohide ? TRUE : FALSE);
  941.                             if (!SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd)) {
  942.                                 user_vars.autohide = !user_vars.autohide;
  943.                                 CheckDlgButton(hDlg, IDC_AUTOHIDE, user_vars.autohide);
  944.                                 ab_message(ERROR_AUTOHIDING);
  945.                                 return FALSE;
  946.                             }
  947.                             // update the position of the autohide bar
  948.                             if (user_vars.autohide) {
  949.                                 abd.rc.top = abd.rc.left = abd.rc.right = abd.rc.bottom = 0;
  950.                                 if (user_vars.bottom)
  951.                                     abd.rc.top = abd.rc.bottom = sys_vars.height;
  952.                                 SHAppBarMessage(ABM_SETPOS, &abd);
  953.                               } else {
  954.                                 abd.rc.top = abd.rc.left = 0;
  955.                                 abd.rc.right = sys_vars.width;
  956.                                 abd.rc.bottom = sys_vars.height;
  957.                                 SHAppBarMessage(ABM_QUERYPOS, &abd);
  958.                                 abd.rc.top = (user_vars.bottom ? abd.rc.bottom - AB_HEIGHT : abd.rc.top);
  959.                                 MoveWindow(ab_hwnd, 0, abd.rc.top, AB_WIDTH, AB_HEIGHT, TRUE);
  960.                                 abd.rc.bottom = abd.rc.top + AB_HEIGHT;
  961.                                 abd.rc.right = AB_WIDTH;
  962.                                 SHAppBarMessage(ABM_SETPOS, &abd);
  963.                             }
  964.                             HideAppBar(user_vars.autohide);
  965.                           } else {
  966.                             ab_message(ERROR_AUTOHIDE_NT);
  967.                             user_vars.autohide = TRUE;
  968.                             CheckDlgButton(hDlg, IDC_AUTOHIDE, user_vars.autohide);
  969.                         }
  970.                         return FALSE;
  971.  
  972.                     case IDC_BOTTOM:
  973.                         user_vars.bottom = !user_vars.bottom;
  974.                         CheckDlgButton(hDlg, IDC_BOTTOM, user_vars.bottom);
  975.                         MoveWindow(ab_hwnd, 0, (user_vars.bottom ? sys_vars.height - AB_HEIGHT : 0),
  976.                                     AB_WIDTH, AB_HEIGHT, TRUE);
  977.                         modify_time();
  978.                         if (sys_vars.newshell) {
  979.                             // we are changing our onscreen position so
  980.                             // we need to reinitialize our appbar system info
  981.                             abd.cbSize = sizeof(APPBARDATA);
  982.                             abd.hWnd = ab_hwnd;
  983.                             abd.uEdge = (user_vars.bottom ? ABE_BOTTOM : ABE_TOP);
  984.                             if (user_vars.autohide) {
  985.                                 abd.lParam = TRUE;
  986.                                 abd.uCallbackMessage = NULL; //WM_APPBAR;
  987.                                 if (!SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd)) {
  988.                                     SHAppBarMessage(ABM_REMOVE, &abd);
  989.                                     SHAppBarMessage(ABM_NEW, &abd);
  990.                                     user_vars.bottom = !user_vars.bottom;
  991.                                     SetWindowPos(ab_hwnd, NULL, 0, (user_vars.bottom ? sys_vars.height - AB_HEIGHT : 0),
  992.                                                             0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  993.                                     abd.uEdge = (user_vars.bottom ? ABE_BOTTOM : ABE_TOP);
  994.                                     SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd);
  995.                                     CheckDlgButton(hDlg, IDC_BOTTOM, user_vars.bottom);
  996.                                     ab_message(ERROR_AUTOHIDING);
  997.                                     return FALSE;
  998.                                 }
  999.                                 HideAppBar(user_vars.autohide);
  1000.                             } else {
  1001.                                 abd.rc.top = abd.rc.left = abd.rc.right = abd.rc.bottom = 0;
  1002.                                 abd.rc.right = sys_vars.width;
  1003.                                 abd.rc.bottom = sys_vars.height;
  1004.                                 SHAppBarMessage(ABM_QUERYPOS, &abd);
  1005.                                 abd.rc.left = 0;
  1006.                                 abd.rc.top = (user_vars.bottom ? abd.rc.bottom - AB_HEIGHT : abd.rc.top);
  1007.                                 abd.rc.bottom = abd.rc.top + AB_HEIGHT;
  1008.                                 abd.rc.right = AB_WIDTH;
  1009.                                 SHAppBarMessage(ABM_SETPOS, &abd);
  1010.                             }
  1011.                         } else 
  1012.                             HideAppBar(TRUE);
  1013.                         return FALSE;
  1014.                     case IDC_STAYONTOP:
  1015.                         user_vars.stayontop = !user_vars.stayontop;
  1016.                         SetWindowPos(ab_hwnd, (user_vars.stayontop ? HWND_TOPMOST : HWND_NOTOPMOST),
  1017.                                         0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  1018.                         return FALSE;
  1019.                     case IDC_FINDWAV:
  1020.                         DoBrowse(1, hDlg);
  1021.                         return FALSE;
  1022.                     case IDC_TESTWAV:
  1023.                         SendMessage(GetDlgItem(hDlg, IDC_WAVNAME), WM_GETTEXT, sizeof(buffer), (LPARAM)buffer);
  1024.                         if (!strcmp(buffer, "")) {
  1025.                             ab_message(ERROR_ENTER_WAVNAME);
  1026.                             return FALSE;
  1027.                         }
  1028.                         if (!PlaySound(buffer, NULL, SND_ASYNC | SND_FILENAME))
  1029.                             ab_message(ERROR_PLAYING_WAV);
  1030.                         return FALSE;
  1031.                 }
  1032.             }
  1033.         default:
  1034.             return FALSE;
  1035.     }
  1036. }
  1037.  
  1038.  
  1039. ///// Whew, these functions are NOT pretty... /////
  1040.  
  1041. BOOL switch_places_a(app_struct *app, int dir)
  1042. {
  1043.     if (!app)
  1044.         return FALSE;
  1045.     if (!(app->prevapp) && (dir == UP))
  1046.         return FALSE;
  1047.     if (!(app->nextapp) && (dir == DOWN))
  1048.         return FALSE;
  1049.     if (dir == UP) {
  1050.         if (app->nextapp)
  1051.             app->nextapp->prevapp = app->prevapp;
  1052.         if (app->prevapp->prevapp)
  1053.             app->prevapp->prevapp->nextapp = app;
  1054.         app->prevapp->nextapp = app->nextapp;
  1055.         app->nextapp = app->prevapp;
  1056.         app->prevapp = app->prevapp->prevapp;
  1057.         app->nextapp->prevapp = app;
  1058.         return TRUE;
  1059.       } else {
  1060.         if (app->prevapp)
  1061.             app->prevapp->nextapp = app->nextapp;
  1062.         if (app->nextapp->nextapp)
  1063.             app->nextapp->nextapp->prevapp = app;
  1064.         app->nextapp->prevapp = app->prevapp;
  1065.         app->prevapp = app->nextapp;
  1066.         app->nextapp = app->nextapp->nextapp;
  1067.         app->prevapp->nextapp = app;
  1068.         return TRUE;
  1069.     }
  1070. }
  1071.  
  1072. BOOL switch_places_m(menu_struct *menu, int dir)
  1073. {
  1074.     if (!menu)
  1075.         return FALSE;
  1076.     if (!(menu->prevmenu) && (dir == UP))
  1077.         return FALSE;
  1078.     if (!(menu->nextmenu) && (dir == DOWN))
  1079.         return FALSE;
  1080.     if (dir == UP) {
  1081.         if (menu->nextmenu)
  1082.             menu->nextmenu->prevmenu = menu->prevmenu;
  1083.         if (menu->prevmenu->prevmenu)
  1084.             menu->prevmenu->prevmenu->nextmenu = menu;
  1085.           else
  1086.             glob_menu = menu;
  1087.         menu->prevmenu->nextmenu = menu->nextmenu;
  1088.         menu->nextmenu = menu->prevmenu;
  1089.         menu->prevmenu = menu->prevmenu->prevmenu;
  1090.         menu->nextmenu->prevmenu = menu;
  1091.         return TRUE;
  1092.       } else {
  1093.         if (menu->prevmenu)
  1094.             menu->prevmenu->nextmenu = menu->nextmenu;
  1095.           else
  1096.             glob_menu = menu->nextmenu;
  1097.         if (menu->nextmenu->nextmenu)
  1098.             menu->nextmenu->nextmenu->prevmenu = menu;
  1099.         menu->nextmenu->prevmenu = menu->prevmenu;
  1100.         menu->prevmenu = menu->nextmenu;
  1101.         menu->nextmenu = menu->nextmenu->nextmenu;
  1102.         menu->prevmenu->nextmenu = menu;
  1103.         return TRUE;
  1104.     }
  1105. }
  1106.